From 4284a039387c3509320e9265bf800ae551fb32b7 Mon Sep 17 00:00:00 2001 From: "djm@kirby.fc.hp.com" Date: Thu, 13 Oct 2005 14:24:45 -0600 Subject: [PATCH] Some outstanding bug fixes found in VT merge - Consistence of region id mangling algrithm: - Metaphysical RID is not mangled, which may conflict with other domain's virtual RID - Sometimes rr0 is mangled, but sometimes not - Sometimes only rid value is saved to saved_rr0_metaphysical, but sometimes the whole value. - Nat bit comsumption happens but handled as priv_emulate to forward progress. But this is definitely wrong. We found reason of nat consumption from fast_rfi, which doesn't save unat again after spill guest states, and then use guest unat to fill guest states when return. - In some corner case, timer interrupt handler won't update itm and then return directly. When that happens, machine timer interrupt disappears until guest timer interrupt sets v_itm actively. But vti domain depends on ac_timer while the latter will stop when above condition happens. Then if current context is vti domain, context switch disappears and machine halt. Also many compatibility issues to support non-vti and vti domain are solved,eg: - Changing lazy PAL mapping switch to eager switch per domain switch, since vti domain always depends on pal call. - evtchn_notify should also vcpu_wake target domain, since vti domain may block for io emulation. Xenolinux is free of this issue, since it's always runnable. Signed-off-by Kevin Tian Signed-off-by Anthony Xu --- xen/Rules.mk | 1 + xen/arch/ia64/Rules.mk | 2 +- xen/arch/ia64/asm-offsets.c | 3 + xen/arch/ia64/linux-xen/entry.S | 9 +- xen/arch/ia64/vmx/vmx_entry.S | 4 +- xen/arch/ia64/vmx/vmx_init.c | 140 ++++++++++++----------------- xen/arch/ia64/vmx/vmx_irq_ia64.c | 5 +- xen/arch/ia64/vmx/vmx_process.c | 8 +- xen/arch/ia64/vmx/vmx_support.c | 2 +- xen/arch/ia64/vmx/vtlb.c | 9 ++ xen/arch/ia64/xen/dom0_ops.c | 9 +- xen/arch/ia64/xen/dom_fw.c | 2 +- xen/arch/ia64/xen/domain.c | 16 +++- xen/arch/ia64/xen/hyperprivop.S | 3 + xen/arch/ia64/xen/ivt.S | 21 +++++ xen/arch/ia64/xen/process.c | 2 + xen/arch/ia64/xen/regionreg.c | 21 +++-- xen/arch/ia64/xen/vcpu.c | 2 + xen/arch/ia64/xen/xenasm.S | 25 +++++- xen/arch/ia64/xen/xenmisc.c | 7 +- xen/arch/ia64/xen/xentime.c | 19 ++-- xen/include/asm-ia64/config.h | 2 +- xen/include/asm-ia64/event.h | 15 ++++ xen/include/asm-ia64/mm.h | 7 +- xen/include/asm-ia64/vmx.h | 1 + xen/include/asm-ia64/xenkregs.h | 3 +- xen/include/public/arch-ia64.h | 27 ++++++ xen/include/public/io/ioreq.h | 14 +-- xen/include/public/io/vmx_vlapic.h | 44 ++------- 29 files changed, 258 insertions(+), 165 deletions(-) diff --git a/xen/Rules.mk b/xen/Rules.mk index d57ca65e51..a1ae2c31b5 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -47,6 +47,7 @@ test-gcc-flag = $(shell $(CC) -v --help 2>&1 | grep -q " $(1) " && echo $(1)) include $(BASEDIR)/arch/$(TARGET_ARCH)/Rules.mk +CFLAGS += -D__HYPERVISOR__ ifneq ($(debug),y) CFLAGS += -DNDEBUG ifeq ($(verbose),y) diff --git a/xen/arch/ia64/Rules.mk b/xen/arch/ia64/Rules.mk index 8eb31cc674..279761d893 100644 --- a/xen/arch/ia64/Rules.mk +++ b/xen/arch/ia64/Rules.mk @@ -24,7 +24,7 @@ CFLAGS += -I$(BASEDIR)/include/asm-ia64 -I$(BASEDIR)/include/asm-ia64/linux \ -I$(BASEDIR)/include/asm-ia64/linux-null \ -I$(BASEDIR)/arch/ia64/linux -I$(BASEDIR)/arch/ia64/linux-xen CFLAGS += -Wno-pointer-arith -Wredundant-decls -CFLAGS += -DIA64 -DXEN -DLINUX_2_6 +CFLAGS += -DIA64 -DXEN -DLINUX_2_6 -DV_IOSAPIC_READY CFLAGS += -ffixed-r13 -mfixed-range=f12-f15,f32-f127 CFLAGS += -w -g ifeq ($(VALIDATE_VT),y) diff --git a/xen/arch/ia64/asm-offsets.c b/xen/arch/ia64/asm-offsets.c index ed770ee725..e1703d09fe 100644 --- a/xen/arch/ia64/asm-offsets.c +++ b/xen/arch/ia64/asm-offsets.c @@ -59,6 +59,8 @@ void foo(void) DEFINE(XSI_BANKNUM_OFS, offsetof(mapped_regs_t, banknum)); DEFINE(XSI_BANK0_OFS, offsetof(mapped_regs_t, bank0_regs[0])); DEFINE(XSI_BANK1_OFS, offsetof(mapped_regs_t, bank1_regs[0])); + DEFINE(XSI_B0NATS_OFS, offsetof(mapped_regs_t, vbnat)); + DEFINE(XSI_B1NATS_OFS, offsetof(mapped_regs_t, vnat)); DEFINE(XSI_RR0_OFS, offsetof(mapped_regs_t, rrs[0])); DEFINE(XSI_METAPHYS_OFS, offsetof(mapped_regs_t, metaphysical_mode)); DEFINE(XSI_PRECOVER_IFS_OFS, offsetof(mapped_regs_t, precover_ifs)); @@ -79,6 +81,7 @@ void foo(void) //DEFINE(IA64_TASK_SIGHAND_OFFSET,offsetof (struct task_struct, sighand)); //DEFINE(IA64_TASK_SIGNAL_OFFSET,offsetof (struct task_struct, signal)); //DEFINE(IA64_TASK_TGID_OFFSET, offsetof (struct task_struct, tgid)); + DEFINE(IA64_PGD, offsetof(struct domain, arch.mm)); DEFINE(IA64_TASK_THREAD_KSP_OFFSET, offsetof (struct vcpu, arch._thread.ksp)); DEFINE(IA64_TASK_THREAD_ON_USTACK_OFFSET, offsetof (struct vcpu, arch._thread.on_ustack)); diff --git a/xen/arch/ia64/linux-xen/entry.S b/xen/arch/ia64/linux-xen/entry.S index c4f2448942..32aebf984e 100644 --- a/xen/arch/ia64/linux-xen/entry.S +++ b/xen/arch/ia64/linux-xen/entry.S @@ -900,10 +900,17 @@ GLOBAL_ENTRY(ia64_leave_kernel) adds r7 = PT(EML_UNAT)+16,r12 ;; ld8 r7 = [r7] + ;; +#if 0 +leave_kernel_self: + cmp.ne p8,p0 = r0, r7 +(p8) br.sptk.few leave_kernel_self + ;; +#endif (p6) br.call.sptk.many b0=deliver_pending_interrupt ;; mov ar.pfs=loc0 - mov ar.unat=r7 /* load eml_unat */ + mov ar.unat=r7 /* load eml_unat */ mov r31=r0 diff --git a/xen/arch/ia64/vmx/vmx_entry.S b/xen/arch/ia64/vmx/vmx_entry.S index 4eda79cc9d..da5cb215f9 100644 --- a/xen/arch/ia64/vmx/vmx_entry.S +++ b/xen/arch/ia64/vmx/vmx_entry.S @@ -720,11 +720,11 @@ GLOBAL_ENTRY(vmx_switch_rr7) // re-pin mappings for guest_vhpt - mov r24=IA64_TR_VHPT + mov r24=IA64_TR_PERVP_VHPT movl r25=PAGE_KERNEL ;; or loc5 = r25,loc5 // construct PA | page properties - mov r23 = VCPU_TLB_SHIFT<<2 + mov r23 = IA64_GRANULE_SHIFT <<2 ;; ptr.d in3,r23 ;; diff --git a/xen/arch/ia64/vmx/vmx_init.c b/xen/arch/ia64/vmx/vmx_init.c index d6b9d24f03..452a96e093 100644 --- a/xen/arch/ia64/vmx/vmx_init.c +++ b/xen/arch/ia64/vmx/vmx_init.c @@ -47,6 +47,7 @@ #include #include #include +#include /* Global flag to identify whether Intel vmx feature is on */ u32 vmx_enabled = 0; @@ -136,39 +137,6 @@ vmx_init_env(void) #endif } -void vmx_setup_platform(struct vcpu *v, struct vcpu_guest_context *c) -{ - struct domain *d = v->domain; - shared_iopage_t *sp; - - ASSERT(d != dom0); /* only for non-privileged vti domain */ - d->arch.vmx_platform.shared_page_va = __va(c->share_io_pg); - sp = get_sp(d); - memset((char *)sp,0,PAGE_SIZE); - /* FIXME: temp due to old CP */ - sp->sp_global.eport = 2; -#ifdef V_IOSAPIC_READY - sp->vcpu_number = 1; -#endif - /* TEMP */ - d->arch.vmx_platform.pib_base = 0xfee00000UL; - - /* One more step to enable interrupt assist */ - set_bit(ARCH_VMX_INTR_ASSIST, &v->arch.arch_vmx.flags); - /* Only open one port for I/O and interrupt emulation */ - if (v == d->vcpu[0]) { - memset(&d->shared_info->evtchn_mask[0], 0xff, - sizeof(d->shared_info->evtchn_mask)); - clear_bit(iopacket_port(d), &d->shared_info->evtchn_mask[0]); - } - - /* FIXME: only support PMT table continuously by far */ -// d->arch.pmt = __va(c->pt_base); - - - vmx_final_setup_domain(d); -} - typedef union { u64 value; struct { @@ -376,40 +344,6 @@ vmx_final_setup_domain(struct domain *d) /* Other vmx specific initialization work */ } -/* - * Following stuff should really move to domain builder. However currently - * XEN/IA64 doesn't export physical -> machine page table to domain builder, - * instead only the copy. Also there's no hypercall to notify hypervisor - * IO ranges by far. Let's enhance it later. - */ - -#define MEM_G (1UL << 30) -#define MEM_M (1UL << 20) - -#define MMIO_START (3 * MEM_G) -#define MMIO_SIZE (512 * MEM_M) - -#define VGA_IO_START 0xA0000UL -#define VGA_IO_SIZE 0x20000 - -#define LEGACY_IO_START (MMIO_START + MMIO_SIZE) -#define LEGACY_IO_SIZE (64*MEM_M) - -#define IO_PAGE_START (LEGACY_IO_START + LEGACY_IO_SIZE) -#define IO_PAGE_SIZE PAGE_SIZE - -#define STORE_PAGE_START (IO_PAGE_START + IO_PAGE_SIZE) -#define STORE_PAGE_SIZE PAGE_SIZE - -#define IO_SAPIC_START 0xfec00000UL -#define IO_SAPIC_SIZE 0x100000 - -#define PIB_START 0xfee00000UL -#define PIB_SIZE 0x100000 - -#define GFW_START (4*MEM_G -16*MEM_M) -#define GFW_SIZE (16*MEM_M) - typedef struct io_range { unsigned long start; unsigned long size; @@ -424,18 +358,26 @@ io_range_t io_ranges[] = { {PIB_START, PIB_SIZE, GPFN_PIB}, }; -#define VMX_SYS_PAGES (2 + GFW_SIZE >> PAGE_SHIFT) +#define VMX_SYS_PAGES (2 + (GFW_SIZE >> PAGE_SHIFT)) #define VMX_CONFIG_PAGES(d) ((d)->max_pages - VMX_SYS_PAGES) int vmx_alloc_contig_pages(struct domain *d) { - unsigned int order, i, j; - unsigned long start, end, pgnr, conf_nr; + unsigned int order; + unsigned long i, j, start, end, pgnr, conf_nr; struct pfn_info *page; struct vcpu *v = d->vcpu[0]; ASSERT(!test_bit(ARCH_VMX_CONTIG_MEM, &v->arch.arch_vmx.flags)); + /* Mark I/O ranges */ + for (i = 0; i < (sizeof(io_ranges) / sizeof(io_range_t)); i++) { + for (j = io_ranges[i].start; + j < io_ranges[i].start + io_ranges[i].size; + j += PAGE_SIZE) + map_domain_page(d, j, io_ranges[i].type); + } + conf_nr = VMX_CONFIG_PAGES(d); order = get_order_from_pages(conf_nr); if (unlikely((page = alloc_domheap_pages(d, order, 0)) == NULL)) { @@ -462,32 +404,64 @@ int vmx_alloc_contig_pages(struct domain *d) d->arch.max_pfn = end >> PAGE_SHIFT; - order = get_order_from_pages(VMX_SYS_PAGES); + order = get_order_from_pages(GFW_SIZE >> PAGE_SHIFT); if (unlikely((page = alloc_domheap_pages(d, order, 0)) == NULL)) { printk("Could not allocate order=%d pages for vmx contig alloc\n", order); return -1; } + /* Map guest firmware */ + pgnr = page_to_pfn(page); + for (i = GFW_START; i < GFW_START + GFW_SIZE; i += PAGE_SIZE, pgnr++) + map_domain_page(d, i, pgnr << PAGE_SHIFT); + + if (unlikely((page = alloc_domheap_pages(d, 1, 0)) == NULL)) { + printk("Could not allocate order=1 pages for vmx contig alloc\n"); + return -1; + } + /* Map for shared I/O page and xenstore */ pgnr = page_to_pfn(page); map_domain_page(d, IO_PAGE_START, pgnr << PAGE_SHIFT); pgnr++; map_domain_page(d, STORE_PAGE_START, pgnr << PAGE_SHIFT); - pgnr++; - /* Map guest firmware */ - for (i = GFW_START; i < GFW_START + GFW_SIZE; i += PAGE_SIZE, pgnr++) - map_domain_page(d, i, pgnr << PAGE_SHIFT); + set_bit(ARCH_VMX_CONTIG_MEM, &v->arch.arch_vmx.flags); + return 0; +} - /* Mark I/O ranges */ - for (i = 0; i < (sizeof(io_ranges) / sizeof(io_range_t)); i++) { - for (j = io_ranges[i].start; - j < io_ranges[i].start + io_ranges[i].size; - j += PAGE_SIZE) - map_domain_page(d, j, io_ranges[i].type); +void vmx_setup_platform(struct vcpu *v, struct vcpu_guest_context *c) +{ + struct domain *d = v->domain; + shared_iopage_t *sp; + + ASSERT(d != dom0); /* only for non-privileged vti domain */ + d->arch.vmx_platform.shared_page_va = + __va(__gpa_to_mpa(d, IO_PAGE_START)); + sp = get_sp(d); + //memset((char *)sp,0,PAGE_SIZE); + //sp->sp_global.eport = 2; +#ifdef V_IOSAPIC_READY + sp->vcpu_number = 1; +#endif + /* TEMP */ + d->arch.vmx_platform.pib_base = 0xfee00000UL; + + /* One more step to enable interrupt assist */ + set_bit(ARCH_VMX_INTR_ASSIST, &v->arch.arch_vmx.flags); + /* Only open one port for I/O and interrupt emulation */ + if (v == d->vcpu[0]) { + memset(&d->shared_info->evtchn_mask[0], 0xff, + sizeof(d->shared_info->evtchn_mask)); + clear_bit(iopacket_port(d), &d->shared_info->evtchn_mask[0]); } - set_bit(ARCH_VMX_CONTIG_MEM, &v->arch.arch_vmx.flags); - return 0; + /* FIXME: only support PMT table continuously by far */ +// d->arch.pmt = __va(c->pt_base); + + + vmx_final_setup_domain(d); } + + diff --git a/xen/arch/ia64/vmx/vmx_irq_ia64.c b/xen/arch/ia64/vmx/vmx_irq_ia64.c index 84af87da41..0bceaa82fd 100644 --- a/xen/arch/ia64/vmx/vmx_irq_ia64.c +++ b/xen/arch/ia64/vmx/vmx_irq_ia64.c @@ -101,7 +101,10 @@ vmx_ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) if (vector != IA64_TIMER_VECTOR) { /* FIXME: Leave IRQ re-route later */ - vmx_vcpu_pend_interrupt(dom0->vcpu[0],vector); + if (!VMX_DOMAIN(dom0->vcpu[0])) + vcpu_pend_interrupt(dom0->vcpu[0],vector); + else + vmx_vcpu_pend_interrupt(dom0->vcpu[0],vector); wake_dom0 = 1; } else { // FIXME: Handle Timer only now diff --git a/xen/arch/ia64/vmx/vmx_process.c b/xen/arch/ia64/vmx/vmx_process.c index 0f9566e7b8..2d7d889733 100644 --- a/xen/arch/ia64/vmx/vmx_process.c +++ b/xen/arch/ia64/vmx/vmx_process.c @@ -271,7 +271,7 @@ void vmx_hpw_miss(u64 vadr , u64 vec, REGS* regs) { IA64_PSR vpsr; CACHE_LINE_TYPE type; - u64 vhpt_adr; + u64 vhpt_adr, gppa; ISR misr; ia64_rr vrr; REGS *regs; @@ -314,9 +314,9 @@ void vmx_hpw_miss(u64 vadr , u64 vec, REGS* regs) // prepare_if_physical_mode(v); if(data=vtlb_lookup_ex(vtlb, vrr.rid, vadr,type)){ - if(v->domain!=dom0&&type==DSIDE_TLB && __gpfn_is_io(v->domain,data->ppn>>(PAGE_SHIFT-12))){ - vadr=(vadr&((1UL<ps)-1))+(data->ppn>>(data->ps-12)<ps); - emulate_io_inst(v, vadr, data->ma); + gppa = (vadr&((1UL<ps)-1))+(data->ppn>>(data->ps-12)<ps); + if(v->domain!=dom0&&type==DSIDE_TLB && __gpfn_is_io(v->domain,gppa>>PAGE_SHIFT)){ + emulate_io_inst(v, gppa, data->ma); return IA64_FAULT; } diff --git a/xen/arch/ia64/vmx/vmx_support.c b/xen/arch/ia64/vmx/vmx_support.c index afd0f650d0..5bf06c8c71 100644 --- a/xen/arch/ia64/vmx/vmx_support.c +++ b/xen/arch/ia64/vmx/vmx_support.c @@ -158,7 +158,7 @@ void vmx_intr_assist(struct vcpu *v) #ifdef V_IOSAPIC_READY vlapic_update_ext_irq(v); #else - panic("IOSAPIC model is missed in qemu\n"); + //panic("IOSAPIC model is missed in qemu\n"); #endif return; } diff --git a/xen/arch/ia64/vmx/vtlb.c b/xen/arch/ia64/vmx/vtlb.c index 78e0b897cb..2d726efe21 100644 --- a/xen/arch/ia64/vmx/vtlb.c +++ b/xen/arch/ia64/vmx/vtlb.c @@ -387,6 +387,15 @@ void vtlb_insert(thash_cb_t *hcb, thash_data_t *entry, u64 va) thash_insert(hcb->ts->vhpt, entry, va); return; } + +#if 1 + vrr=vmx_vcpu_rr(current, va); + if (vrr.ps != entry->ps) { + printk("not preferred ps with va: 0x%lx\n", va); + return; + } +#endif + flag = 1; gppn = (POFFSET(va,entry->ps)|PAGEALIGN((entry->ppn<<12),entry->ps))>>PAGE_SHIFT; ppns = PAGEALIGN((entry->ppn<<12),entry->ps); diff --git a/xen/arch/ia64/xen/dom0_ops.c b/xen/arch/ia64/xen/dom0_ops.c index 48517604f7..540e09caa4 100644 --- a/xen/arch/ia64/xen/dom0_ops.c +++ b/xen/arch/ia64/xen/dom0_ops.c @@ -177,13 +177,8 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op) for ( i = start_page; i < (start_page + nr_pages); i++ ) { - page = map_new_domain_page(d, i << PAGE_SHIFT); - if ( page == NULL ) - { - ret = -ENOMEM; - break; - } - pfn = page_to_pfn(page); + pfn = __gpfn_to_mfn_foreign(d, i); + if ( put_user(pfn, buffer) ) { ret = -EFAULT; diff --git a/xen/arch/ia64/xen/dom_fw.c b/xen/arch/ia64/xen/dom_fw.c index ca22fafacc..eb9fbe8858 100644 --- a/xen/arch/ia64/xen/dom_fw.c +++ b/xen/arch/ia64/xen/dom_fw.c @@ -301,7 +301,7 @@ xen_pal_emulator(unsigned long index, unsigned long in1, // pal code must be mapped by a TR when pal is called, however // calls are rare enough that we will map it lazily rather than // at every context switch - efi_map_pal_code(); + //efi_map_pal_code(); switch (index) { case PAL_MEM_ATTRIB: status = ia64_pal_mem_attrib(&r9); diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 7c9b0ddc11..f48cdff759 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -59,6 +59,7 @@ unsigned long *domU_staging_area; // initialized by arch/ia64/setup.c:find_initrd() unsigned long initrd_start = 0, initrd_end = 0; +extern unsigned long running_on_sim; #define IS_XEN_ADDRESS(d,a) ((a >= d->xen_vastart) && (a <= d->xen_vaend)) @@ -190,6 +191,9 @@ void arch_do_createdomain(struct vcpu *v) while (1); } memset(d->shared_info, 0, PAGE_SIZE); + if (v == d->vcpu[0]) + memset(&d->shared_info->evtchn_mask[0], 0xff, + sizeof(d->shared_info->evtchn_mask)); #if 0 d->vcpu[0].arch.privregs = alloc_xenheap_pages(get_order(sizeof(mapped_regs_t))); @@ -271,6 +275,14 @@ int arch_set_info_guest(struct vcpu *v, struct vcpu_guest_context *c) if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) ) return 0; + /* Sync d/i cache conservatively */ + if (!running_on_sim) { + ret = ia64_pal_cache_flush(4, 0, &progress, NULL); + if (ret != PAL_STATUS_SUCCESS) + panic("PAL CACHE FLUSH failed for domain.\n"); + printk("Sync i/d cache for dom0 image SUCC\n"); + } + if (c->flags & VGCF_VMX_GUEST) { if (!vmx_enabled) { printk("No VMX hardware feature for vmx domain.\n"); @@ -547,7 +559,8 @@ tryagain: if (pte_present(*pte)) { //printk("lookup_domain_page: found mapping for %lx, pte=%lx\n",mpaddr,pte_val(*pte)); return *(unsigned long *)pte; - } + } else if (VMX_DOMAIN(d->vcpu[0])) + return GPFN_INV_MASK; } } } @@ -799,7 +812,6 @@ void physdev_init_dom0(struct domain *d) set_bit(_DOMF_physdev_access, &d->domain_flags); } -extern unsigned long running_on_sim; unsigned int vmx_dom0 = 0; int construct_dom0(struct domain *d, unsigned long image_start, unsigned long image_len, diff --git a/xen/arch/ia64/xen/hyperprivop.S b/xen/arch/ia64/xen/hyperprivop.S index e20b5d91e3..d472806a1e 100644 --- a/xen/arch/ia64/xen/hyperprivop.S +++ b/xen/arch/ia64/xen/hyperprivop.S @@ -807,8 +807,11 @@ just_do_rfi: // OK, now all set to go except for switch to virtual bank1 mov r22=1;; st4 [r20]=r22; mov r30=r2; mov r29=r3;; + adds r16=XSI_B1NATS_OFS-XSI_PSR_IC_OFS,r18 adds r2=XSI_BANK1_OFS-XSI_PSR_IC_OFS,r18; adds r3=(XSI_BANK1_OFS+8)-XSI_PSR_IC_OFS,r18;; + ld8 r16=[r16];; + mov ar.unat=r16;; bsw.1;; // FIXME?: ar.unat is not really handled correctly, // but may not matter if the OS is NaT-clean diff --git a/xen/arch/ia64/xen/ivt.S b/xen/arch/ia64/xen/ivt.S index 5f7b4db205..1477bbe18e 100644 --- a/xen/arch/ia64/xen/ivt.S +++ b/xen/arch/ia64/xen/ivt.S @@ -1460,7 +1460,28 @@ END(general_exception) // 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35) ENTRY(disabled_fp_reg) #ifdef XEN +#if 0 + mov r20=pr + movl r16=0x2000000000000000 + movl r17=0x2000000000176b60 + mov r18=cr.iip + mov r19=rr[r16] + movl r22=0xe95d0439 + ;; + mov pr=r0,-1 + ;; + cmp.eq p6,p7=r22,r19 + ;; + (p6) cmp.eq p8,p9=r17,r18 + (p8) br.sptk.few floating_panic + ;; + mov pr=r20,-1 + ;; +#endif REFLECT(25) +//floating_panic: +// br.sptk.many floating_panic + ;; #endif DBG_FAULT(25) rsm psr.dfh // ensure we can access fph diff --git a/xen/arch/ia64/xen/process.c b/xen/arch/ia64/xen/process.c index 1432002032..c3eb890a8b 100644 --- a/xen/arch/ia64/xen/process.c +++ b/xen/arch/ia64/xen/process.c @@ -745,6 +745,8 @@ ia64_handle_reflection (unsigned long ifa, struct pt_regs *regs, unsigned long i case 26: printf("*** NaT fault... attempting to handle as privop\n"); printf("isr=%p, ifa=%p,iip=%p,ipsr=%p\n",isr,ifa,regs->cr_iip,psr); + regs->eml_unat = 0; + return; vector = priv_emulate(v,regs,isr); if (vector == IA64_NO_FAULT) { printf("*** Handled privop masquerading as NaT fault\n"); diff --git a/xen/arch/ia64/xen/regionreg.c b/xen/arch/ia64/xen/regionreg.c index 418ba8df23..2e0bb6425f 100644 --- a/xen/arch/ia64/xen/regionreg.c +++ b/xen/arch/ia64/xen/regionreg.c @@ -15,7 +15,8 @@ #include #include #include -extern void ia64_new_rr7(unsigned long rid,void *shared_info, void *shared_arch_info); +extern void ia64_new_rr7(unsigned long rid,void *shared_info, void *shared_arch_info, unsigned long p_vhpt, unsigned long v_pal); +extern void *pal_vaddr; #define IA64_MIN_IMPL_RID_BITS (IA64_MIN_IMPL_RID_MSB+1) @@ -66,9 +67,12 @@ unsigned long allocate_metaphysical_rr(void) { ia64_rr rrv; + rrv.rrval = 0; // Or else may see reserved bit fault rrv.rid = allocate_reserved_rid(); rrv.ps = PAGE_SHIFT; rrv.ve = 0; + /* Mangle metaphysical rid */ + rrv.rrval = vmMangleRID(rrv.rrval); return rrv.rrval; } @@ -213,6 +217,7 @@ int set_one_rr(unsigned long rr, unsigned long val) unsigned long rreg = REGION_NUMBER(rr); ia64_rr rrv, newrrv, memrrv; unsigned long newrid; + extern unsigned long vhpt_paddr; if (val == -1) return 1; @@ -250,9 +255,10 @@ int set_one_rr(unsigned long rr, unsigned long val) newrrv.rid = newrid; newrrv.ve = 1; // VHPT now enabled for region 7!! newrrv.ps = PAGE_SHIFT; - if (rreg == 0) v->arch.metaphysical_saved_rr0 = newrrv.rrval; + if (rreg == 0) v->arch.metaphysical_saved_rr0 = + vmMangleRID(newrrv.rrval); if (rreg == 7) ia64_new_rr7(vmMangleRID(newrrv.rrval),v->vcpu_info, - v->arch.privregs); + v->arch.privregs, vhpt_paddr, pal_vaddr); else set_rr(rr,newrrv.rrval); #endif return 1; @@ -265,7 +271,8 @@ int set_metaphysical_rr0(void) ia64_rr rrv; // rrv.ve = 1; FIXME: TURN ME BACK ON WHEN VHPT IS WORKING - set_rr(0,v->arch.metaphysical_rr0); + ia64_set_rr(0,v->arch.metaphysical_rr0); + ia64_srlz_d(); } // validates/changes region registers 0-6 in the currently executing domain @@ -290,7 +297,7 @@ void init_all_rr(struct vcpu *v) ia64_rr rrv; rrv.rrval = 0; - rrv.rrval = v->domain->arch.metaphysical_rr0; + //rrv.rrval = v->domain->arch.metaphysical_rr0; rrv.ps = PAGE_SHIFT; rrv.ve = 1; if (!v->vcpu_info) { printf("Stopping in init_all_rr\n"); dummy(); } @@ -343,12 +350,16 @@ unsigned long load_region_regs(struct vcpu *v) if (VCPU(v,metaphysical_mode)) { ia64_rr rrv; +#if 0 rrv.rrval = 0; rrv.rid = v->domain->arch.metaphysical_rr0; rrv.ps = PAGE_SHIFT; rrv.ve = 1; rr0 = rrv.rrval; set_rr_no_srlz(0x0000000000000000L, rr0); +#endif + rr0 = v->domain->arch.metaphysical_rr0; + ia64_set_rr(0x0000000000000000L, rr0); ia64_srlz_d(); } else { diff --git a/xen/arch/ia64/xen/vcpu.c b/xen/arch/ia64/xen/vcpu.c index f3990a6cf5..15d897ef0d 100644 --- a/xen/arch/ia64/xen/vcpu.c +++ b/xen/arch/ia64/xen/vcpu.c @@ -775,6 +775,7 @@ IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT64 *pval) } #ifdef HEARTBEAT_FREQ if (domid >= N_DOMS) domid = N_DOMS-1; +#if 0 if (vector == (PSCB(vcpu,itv) & 0xff)) { if (!(++count[domid] & ((HEARTBEAT_FREQ*1024)-1))) { printf("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n", @@ -783,6 +784,7 @@ IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT64 *pval) //dump_runq(); } } +#endif else nonclockcount[domid]++; #endif // now have an unmasked, pending, deliverable vector! diff --git a/xen/arch/ia64/xen/xenasm.S b/xen/arch/ia64/xen/xenasm.S index 92b47cc976..216aeefd7b 100644 --- a/xen/arch/ia64/xen/xenasm.S +++ b/xen/arch/ia64/xen/xenasm.S @@ -48,11 +48,11 @@ END(platform_is_hp_ski) // FIXME? Note that this turns off the DB bit (debug) #define PSR_BITS_TO_SET IA64_PSR_BN -//extern void ia64_new_rr7(unsigned long rid,void *shared_info, void *shared_arch_info); +//extern void ia64_new_rr7(unsigned long rid,void *shared_info, void *shared_arch_info, unsigned long p_vhpt, unsigned long v_pal); GLOBAL_ENTRY(ia64_new_rr7) // not sure this unwind statement is correct... .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(1) - alloc loc1 = ar.pfs, 3, 8, 0, 0 + alloc loc1 = ar.pfs, 5, 9, 0, 0 1: { mov r28 = in0 // copy procedure index mov r8 = ip // save ip to compute branch @@ -63,10 +63,12 @@ GLOBAL_ENTRY(ia64_new_rr7) ;; tpa loc2=loc2 // grab this BEFORE changing rr7 ;; + dep loc8=0,in4,60,4 + ;; #if VHPT_ENABLED - movl loc6=VHPT_ADDR + mov loc6=in3 ;; - tpa loc6=loc6 // grab this BEFORE changing rr7 + //tpa loc6=loc6 // grab this BEFORE changing rr7 ;; #endif mov loc5=in1 @@ -231,6 +233,21 @@ GLOBAL_ENTRY(ia64_new_rr7) itr.d dtr[r25]=r23 // wire in new mapping... ;; + //Purge/insert PAL TR + mov r24=IA64_TR_PALCODE + movl r25=PAGE_KERNEL + ;; + or loc8=r25,loc8 + mov r23=IA64_GRANULE_SHIFT<<2 + ;; + ptr.i in4,r23 + ;; + mov cr.itir=r23 + mov cr.ifa=in4 + ;; + itr.i itr[r24]=loc8 + ;; + // done, switch back to virtual and return mov r16=loc3 // r16= original psr br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode diff --git a/xen/arch/ia64/xen/xenmisc.c b/xen/arch/ia64/xen/xenmisc.c index e62115ebbd..a51059174c 100644 --- a/xen/arch/ia64/xen/xenmisc.c +++ b/xen/arch/ia64/xen/xenmisc.c @@ -17,6 +17,7 @@ #include #include #include +#include efi_memory_desc_t ia64_efi_io_md; EXPORT_SYMBOL(ia64_efi_io_md); @@ -310,9 +311,13 @@ if (!cnt[id]--) { printk("%x",id); cnt[id] = 500000; } if (!i--) { printk("+",id); i = 1000000; } } - if (VMX_DOMAIN(current)){ + if (VMX_DOMAIN(current)){ vmx_load_all_rr(current); }else{ + extern char ia64_ivt; + ia64_set_iva(&ia64_ivt); + ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) | + VHPT_ENABLED); if (!is_idle_task(current->domain)) { load_region_regs(current); if (vcpu_timer_expired(current)) vcpu_pend_timer(current); diff --git a/xen/arch/ia64/xen/xentime.c b/xen/arch/ia64/xen/xentime.c index 75a454b0ed..cdd17b0673 100644 --- a/xen/arch/ia64/xen/xentime.c +++ b/xen/arch/ia64/xen/xentime.c @@ -99,6 +99,7 @@ xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) { unsigned long new_itm, old_itc; +#if 0 #define HEARTBEAT_FREQ 16 // period in seconds #ifdef HEARTBEAT_FREQ static long count = 0; @@ -109,6 +110,7 @@ xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) VCPU(current,pending_interruption) */); count = 0; } +#endif #endif if (current->domain == dom0) { // FIXME: there's gotta be a better way of doing this... @@ -117,12 +119,14 @@ xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) //domain0_ready = 1; // moved to xensetup.c VCPU(current,pending_interruption) = 1; } - if (domain0_ready && vcpu_timer_expired(dom0->vcpu[0])) { - vcpu_pend_timer(dom0->vcpu[0]); - //vcpu_set_next_timer(dom0->vcpu[0]); - vcpu_wake(dom0->vcpu[0]); + if (domain0_ready && current->domain != dom0) { + if(vcpu_timer_expired(dom0->vcpu[0])) { + vcpu_pend_timer(dom0->vcpu[0]); + //vcpu_set_next_timer(dom0->vcpu[0]); + vcpu_wake(dom0->vcpu[0]); + } } - if (!is_idle_task(current->domain) && current->domain != dom0) { + if (!is_idle_task(current->domain)) { if (vcpu_timer_expired(current)) { vcpu_pend_timer(current); // ensure another timer interrupt happens even if domain doesn't @@ -132,9 +136,12 @@ xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) } new_itm = local_cpu_data->itm_next; - if (!time_after(ia64_get_itc(), new_itm)) + if (!VMX_DOMAIN(current) && !time_after(ia64_get_itc(), new_itm)) return; + if (VMX_DOMAIN(current)) + vcpu_wake(current); + while (1) { new_itm += local_cpu_data->itm_delta; diff --git a/xen/include/asm-ia64/config.h b/xen/include/asm-ia64/config.h index 10a9b38739..fec2d5bff3 100644 --- a/xen/include/asm-ia64/config.h +++ b/xen/include/asm-ia64/config.h @@ -102,7 +102,7 @@ extern char _end[]; /* standard ELF symbol */ #endif // xen/include/asm/config.h -#define HZ 100 +//#define HZ 1000 // FIXME SMP: leave SMP for a later time #define barrier() __asm__ __volatile__("": : :"memory") diff --git a/xen/include/asm-ia64/event.h b/xen/include/asm-ia64/event.h index d01111be7c..297351072d 100644 --- a/xen/include/asm-ia64/event.h +++ b/xen/include/asm-ia64/event.h @@ -14,6 +14,21 @@ static inline void evtchn_notify(struct vcpu *v) { + /* + * NB1. 'vcpu_flags' and 'processor' must be checked /after/ update of + * pending flag. These values may fluctuate (after all, we hold no + * locks) but the key insight is that each change will cause + * evtchn_upcall_pending to be polled. + * + * NB2. We save VCPUF_running across the unblock to avoid a needless + * IPI for domains that we IPI'd to unblock. + */ + int running = test_bit(_VCPUF_running, &v->vcpu_flags); + vcpu_unblock(v); + if ( running ) + smp_send_event_check_cpu(v->processor); + + if(!VMX_DOMAIN(v)) vcpu_pend_interrupt(v, v->vcpu_info->arch.evtchn_vector); } diff --git a/xen/include/asm-ia64/mm.h b/xen/include/asm-ia64/mm.h index 100400cb5c..7fac78db61 100644 --- a/xen/include/asm-ia64/mm.h +++ b/xen/include/asm-ia64/mm.h @@ -405,6 +405,7 @@ extern unsigned long totalram_pages; extern int nr_swap_pages; extern unsigned long *mpt_table; +extern unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr); #undef machine_to_phys_mapping #define machine_to_phys_mapping mpt_table @@ -433,10 +434,10 @@ extern unsigned long *mpt_table; #define __gpfn_is_mem(_d, gpfn) \ (__gpfn_valid(_d, gpfn) ? \ - (lookup_domain_mpa((_d), ((gpfn)<>PAGE_SHIFT)<>PAGE_SHIFT)< + extern void identify_vmx_feature(void); extern unsigned int vmx_enabled; extern void vmx_init_env(void); diff --git a/xen/include/asm-ia64/xenkregs.h b/xen/include/asm-ia64/xenkregs.h index 5a0c5c0bd6..3eb48d9ec2 100644 --- a/xen/include/asm-ia64/xenkregs.h +++ b/xen/include/asm-ia64/xenkregs.h @@ -6,7 +6,8 @@ */ #define IA64_TR_SHARED_INFO 3 /* dtr3: page shared with domain */ #define IA64_TR_VHPT 4 /* dtr4: vhpt */ -#define IA64_TR_ARCH_INFO 5 +#define IA64_TR_ARCH_INFO 5 +#define IA64_TR_PERVP_VHPT 6 /* Processor status register bits: */ #define IA64_PSR_VM_BIT 46 diff --git a/xen/include/public/arch-ia64.h b/xen/include/public/arch-ia64.h index e6e5c48f8e..f3bb61a932 100644 --- a/xen/include/public/arch-ia64.h +++ b/xen/include/public/arch-ia64.h @@ -38,6 +38,33 @@ typedef struct { #define INVALID_MFN (~0UL) +#define MEM_G (1UL << 30) +#define MEM_M (1UL << 20) + +#define MMIO_START (3 * MEM_G) +#define MMIO_SIZE (512 * MEM_M) + +#define VGA_IO_START 0xA0000UL +#define VGA_IO_SIZE 0x20000 + +#define LEGACY_IO_START (MMIO_START + MMIO_SIZE) +#define LEGACY_IO_SIZE (64*MEM_M) + +#define IO_PAGE_START (LEGACY_IO_START + LEGACY_IO_SIZE) +#define IO_PAGE_SIZE PAGE_SIZE + +#define STORE_PAGE_START (IO_PAGE_START + IO_PAGE_SIZE) +#define STORE_PAGE_SIZE PAGE_SIZE + +#define IO_SAPIC_START 0xfec00000UL +#define IO_SAPIC_SIZE 0x100000 + +#define PIB_START 0xfee00000UL +#define PIB_SIZE 0x100000 + +#define GFW_START (4*MEM_G -16*MEM_M) +#define GFW_SIZE (16*MEM_M) + /* * NB. This may become a 64-bit count with no shift. If this happens then the * structure size will still be 8 bytes, so no other alignments will change. diff --git a/xen/include/public/io/ioreq.h b/xen/include/public/io/ioreq.h index 5e0b66e501..210810e6af 100644 --- a/xen/include/public/io/ioreq.h +++ b/xen/include/public/io/ioreq.h @@ -35,6 +35,13 @@ #define IOREQ_TYPE_OR 3 #define IOREQ_TYPE_XOR 4 +#ifdef __HYPERVISOR__ +#include +#else +#include +#endif + + /* * VMExit dispatcher should cooperate with instruction decoder to * prepare this structure and notify service OS and DM by sending @@ -55,10 +62,6 @@ typedef struct { u8 type; /* I/O type */ } ioreq_t; -#define MAX_VECTOR 256 -#define BITS_PER_BYTE 8 -#define INTR_LEN (MAX_VECTOR/(BITS_PER_BYTE * sizeof(u64))) - typedef struct { u64 pic_intr[INTR_LEN]; u64 pic_mask[INTR_LEN]; @@ -67,10 +70,11 @@ typedef struct { typedef struct { ioreq_t vp_ioreq; - unsigned long vp_intr[INTR_LEN]; + vl_apic_info apic_intr; } vcpu_iodata_t; typedef struct { + int vcpu_number; global_iodata_t sp_global; vcpu_iodata_t vcpu_iodata[1]; } shared_iopage_t; diff --git a/xen/include/public/io/vmx_vlapic.h b/xen/include/public/io/vmx_vlapic.h index c414329628..c765bb0cc6 100644 --- a/xen/include/public/io/vmx_vlapic.h +++ b/xen/include/public/io/vmx_vlapic.h @@ -1,57 +1,29 @@ #ifndef _VMX_VLAPIC_H #define _VMX_VLAPIC_H -/* - We extended one bit for PIC type - */ #define VLAPIC_DELIV_MODE_FIXED 0x0 #define VLAPIC_DELIV_MODE_LPRI 0x1 #define VLAPIC_DELIV_MODE_SMI 0x2 +#define VLAPIC_DELIV_MODE_PMI 0x2 #define VLAPIC_DELIV_MODE_NMI 0x4 #define VLAPIC_DELIV_MODE_INIT 0x5 #define VLAPIC_DELIV_MODE_STARTUP 0x6 #define VLAPIC_DELIV_MODE_EXT 0x7 #define VLAPIC_DELIV_MODE_MASK 0x8 -#define VLAPIC_MSG_LEVEL 4 - -#define INTR_EXT 0 -#define INTR_APIC 1 -#define INTR_LAPIC 2 - -#define VL_STATE_EOI 1 -#define VL_STATE_EXT_LOCK 2 -#define VL_STATE_MSG_LOCK 3 -#define VL_STATE_EOI_LOCK 3 - -#define VLOCAL_APIC_MAX_INTS 256 -#define VLAPIC_INT_COUNT (VLOCAL_APIC_MAX_INTS/(BITS_PER_BYTE * sizeof(u64))) -#define VLAPIC_INT_COUNT_32 (VLOCAL_APIC_MAX_INTS/(BITS_PER_BYTE * sizeof(u32))) - -struct vapic_bus_message{ - u8 deliv_mode:4; /* deliver mode, including fixed, LPRI, etc */ - u8 level:1; /* level or edge */ - u8 trig_mod:1; /* assert or disassert */ - u8 reserved:2; - u8 vector; -}; +#define MAX_VECTOR 256 +#define BITS_PER_BYTE 8 +#define INTR_LEN (MAX_VECTOR/(BITS_PER_BYTE * sizeof(u64))) +#define INTR_LEN_32 (MAX_VECTOR/(BITS_PER_BYTE * sizeof(u32))) typedef struct { - /* interrupt for PIC and ext type IOAPIC interrupt */ - u64 vl_ext_intr[VLAPIC_INT_COUNT]; - u64 vl_ext_intr_mask[VLAPIC_INT_COUNT]; - u64 vl_apic_intr[VLAPIC_INT_COUNT]; - u64 vl_apic_tmr[VLAPIC_INT_COUNT]; - u64 vl_eoi[VLAPIC_INT_COUNT]; u32 vl_lapic_id; - u32 direct_intr; u32 vl_apr; u32 vl_logical_dest; u32 vl_dest_format; u32 vl_arb_id; - u32 vl_state; - u32 apic_msg_count; - struct vapic_bus_message vl_apic_msg[24]; -} vlapic_info; + u64 irr[INTR_LEN]; + u64 tmr[INTR_LEN]; +}vl_apic_info; #endif /* _VMX_VLAPIC_H_ */ -- 2.30.2